
package com.qiall.gateway.service;

import com.qiall.boot.cache.ability.service.CacheService;
import com.qiall.common.exception.BusinessException;
import com.qiall.common.exception.BusinessResult;
import com.qiall.common.exception.ResultCode;
import com.qiall.gateway.service.dubborpc.DubboRpc;
import com.qiall.oms.constants.OmsManageConstant;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import static com.qiall.oms.constants.OmsManageConstant.CLIENT_CLASS_DATA_CHARSET;


/**
 * @author 吴金辉
 */
public class ByteClassLoader extends ClassLoader {


    private static ByteClassLoader instance;

    private DubboRpc dubboRpc;

    private ByteClassLoader(DubboRpc dubboRpc) {
        this.dubboRpc = dubboRpc;
    }


    @Override
    public Class<?> findClass(String name) {

        String key = name.replaceAll("\\.", "/");

        key = key + ".class";
        String classByte = getClassByte(key);
        byte[] bytes = classByte.getBytes(CLIENT_CLASS_DATA_CHARSET);
        return defineClass(name, bytes, 0, bytes.length);

    }

    @Override
    public Class<?> loadClass(String name) {
        try {
            return super.loadClass(name);
        } catch (Exception e) {
        }

        return findClass(name);
    }

    protected static synchronized ByteClassLoader getInstance(DubboRpc rpc) {
        if (instance == null) {
            instance = new ByteClassLoader(rpc);
        }
        return instance;

    }

    private String getClassByte(String name) {
        List<String> classes = new ArrayList<>();
        classes.add(String.class.getName());
        classes.add(String.class.getName());
        String[] paramsData = {OmsManageConstant.CLIENT_CLASS_NAME_MAP, name};
        Object resp = dubboRpc.genericInvoke(CacheService.class.getName(), "getMapValue", classes, paramsData);
        if (resp instanceof Map) {
            Map<String, String> respMap = (Map) resp;
            return respMap.get("body");
        }
        throw new BusinessException(ResultCode.SYSTEM_ERROR, "class not exit" + name);
    }

}